package com.kelvin.oocl.crm.util;

import java.util.Comparator;
import java.util.Iterator;
import com.kelvin.oocl.crm.exception.LinkListIndexOutOfBoundException;

/**
 * 链表的实现
 * @author MAIKE
 *
 * @param <T>
 */
public class MyLinkList<T> implements Iterable<T>{
	
	private Node<T> head; //头结点
	private Node<T> tail;
	private int size; //链表大小
	
	public MyLinkList() {
		
	}
	
	/**
	 * 清空链表
	 */
	public void clear(){
		if(null==head){
			return;
		}
		Node<T> cNode = head;
		while(cNode!=null){
			Node<T> node = cNode;
			cNode = cNode.getNextNode();
			node.setPreNode(null);
			node.setNextNode(null);
			node = null;
		}
		head = null;
		tail = null;
		size = 0;
	}
	
	/**
	 * 判断是否包含元素
	 * @param t
	 * @return
	 */
	public boolean contains(T t){
		if(null==head || t==null){
			return false;
		}
		Node<T> currNode= head;
		while(currNode != null){
			if(currNode.getValue().equals(t)){
				return true;
			}
			currNode = currNode.getNextNode();
		}
		return false;
	}
	
	/**
	 * 升序或者降序排序,使用冒泡算法
	 * @param asc
	 * @throws Exception 
	 */
	public void sort(Comparator<T> c) throws Exception{
		if(head==null || size==1){
			return;
		}
		Node<T> currNode = head;
		while(currNode != null){
			Node<T> lastNode = tail;
			while(!lastNode.equals(currNode)){
				Node<T> preNode = lastNode.getPreNode();
				if(c.compare(preNode.getValue(), lastNode.getValue())>0){
					T t = preNode.getValue();
					preNode.setValue(lastNode.getValue());
					lastNode.setValue(t);
				}
				lastNode = lastNode.getPreNode();
			}
			currNode = currNode.getNextNode();
		}
	}
	
	/**
	 * 移除节点元素
	 * @param t
	 * @return
	 */
	public boolean remove(T t){
		if(t==null){
			return false;
		}
		if(head==null){
			return false;
		}
		Node<T> currNode = head;
		int temp = size;
		while(currNode!=null){
			if(t.equals(currNode.getValue())){
				Node<T> nextNode = currNode.getNextNode();
				Node<T> preNode = currNode.getPreNode();
				if(nextNode==null){
					this.tail = preNode;
					if(preNode==null){
						this.head = nextNode;
					}else {
						preNode.setNextNode(null);
					}
				}else if(preNode == null){
					this.head = nextNode;
					nextNode.setPreNode(null);
				}else {
					nextNode.setPreNode(preNode);
					preNode.setNextNode(nextNode);
				}
				size--;
			}
			currNode = currNode.getNextNode();
		}
		if(size<temp){
			return true;
		}
		return false;
	}
	
	/**
	 * 插入一个节点
	 * @param t
	 * @return
	 */
	public boolean add(T t){
		if(null==t){
			return false;
		}
		if(tail==null){
			head = new Node<>(t);
			tail = head;
			size++;
		}else {
			Node<T> node = new Node<>(t);
			tail.setNextNode(node);
			node.setPreNode(tail);
			tail = node;
			size++;
		}
		return true;
	}
	
	/**
	 * 根据下标获取节点
	 * @param index
	 * @return
	 */
	public T get(int index) throws LinkListIndexOutOfBoundException{
		if(index<0){
			throw new LinkListIndexOutOfBoundException("The index is less than 0");
		}else if(index+1>size){
			throw new LinkListIndexOutOfBoundException("The index is grater than list size");
		}
		if(head==null){
			return null;
		}
		int i=0;
		Node<T> cNode = head;
		while(cNode!=null){
			if(i==index){
				return cNode.getValue();
			}
			i++;
			cNode = cNode.getNextNode();
		}
		return null;
	}
	
	public void printFormHead(){
		if(head==null)
			return;
		Node<T> currNode = head;
		while(currNode!=null){
			System.out.println(currNode.getValue().toString());
			currNode = currNode.getNextNode();
		}
	}
	
	public int getSize() {
		return size;
	}

	private class Node<E>{
		private E value;
		private Node<E> preNode;
		private Node<E> nextNode;
		
		private Node(E t) {
			this.value = t;
		}
		
		private Node() {
		}

		public E getValue() {
			return value;
		}

		public void setValue(E value) {
			this.value = value;
		}

		public Node<E> getPreNode() {
			return preNode;
		}

		public void setPreNode(Node<E> preNode) {
			this.preNode = preNode;
		}

		public Node<E> getNextNode() {
			return nextNode;
		}

		public void setNextNode(Node<E> nextNode) {
			this.nextNode = nextNode;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + ((value == null) ? 0 : value.hashCode());
			return result;
		}

		@SuppressWarnings("unchecked")
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Node<E> other = (Node<E>) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (value == null) {
				if (other.value != null)
					return false;
			} else if (!value.equals(other.value))
				return false;
			return true;
		}

		@SuppressWarnings("rawtypes")
		private MyLinkList getOuterType() {
			return MyLinkList.this;
		}
	}

	@Override
	public Iterator<T> iterator() {
		return new MyIterator();
	}
	
	class MyIterator implements Iterator<T> {
		private Node<T> lastReturned;
		private Node<T> curr;
		private int currIndex;
		
		MyIterator(){
			curr = (head==null) ? null:head;
			currIndex = 0;
		}

		@Override
		public boolean hasNext() {
			return currIndex < size;
		}

		@Override
		public T next() {
			lastReturned = curr;
			curr = curr.getNextNode();
			currIndex++;
			return lastReturned.getValue();
		}

		@Override
		public void remove() {
			// TODO Auto-generated method stub
			
		}
	}

}
